package org.light.framework.aop;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.light.framework.aop.annotation.Aspect;
import org.light.framework.ioc.BeanHelper;
import org.light.framework.mvc.annotation.Service;
import org.light.framework.util.ClassUtil;

/**
 * 初始化 AOP 框架
 *
 * @author de.cel
 */
public class AopHelper {

	static {
		try {
			// 创建 Proxy Map（用于 存放代理类 与 目标类列表 的映射关系）
			Map<Class<?>, List<Class<?>>> proxyMap = createProxyMap();
			// 创建 Target Map（用于 存放目标类 与 代理类列表 的映射关系）
			Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
			// 遍历 Target Map
			for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {
				// 分别获取 map 中的 key 与 value
				Class<?> targetClass = targetEntry.getKey();
				List<Proxy> proxyList = targetEntry.getValue();
				// 创建代理实例
				Object proxyInstance = ProxyManager.createProxy(targetClass, proxyList);
				// 用代理实例覆盖目标实例，并放入 Bean 容器中
				BeanHelper.setBean(targetClass, proxyInstance);
			}
		} catch (Exception e) {
			System.out.println("初始化 AopHelper 出错！" + e);
		}
	}

	private static Map<Class<?>, List<Class<?>>> createProxyMap() throws Exception {
		Map<Class<?>, List<Class<?>>> proxyMap = new HashMap<Class<?>, List<Class<?>>>();

		// 添加相关代理
		addAspectProxy(proxyMap); // 切面代理
		addTransactionProxy(proxyMap); // 事务代理
		return proxyMap;
	}

	private static void addAspectProxy(Map<Class<?>, List<Class<?>>> proxyMap) throws Exception {
		// 获取切面类（所有继承于 BaseAspect 的类）
		List<Class<?>> aspectProxyClassList = ClassUtil.getClassListBySuper(AspectProxy.class);
		// 遍历切面类
		for (Class<?> aspectProxyClass : aspectProxyClassList) {
			// 判断 Aspect 注解是否存在
			if (aspectProxyClass.isAnnotationPresent(Aspect.class)) {
				// 获取 Aspect 注解
				Aspect aspect = aspectProxyClass.getAnnotation(Aspect.class);
				// 创建目标类列表
				List<Class<?>> targetClassList = createTargetClassList(aspect);
				// 初始化 Proxy Map
				proxyMap.put(aspectProxyClass, targetClassList);
			}
		}
	}

	private static void addTransactionProxy(Map<Class<?>, List<Class<?>>> proxyMap) {
		// 使用 TransactionProxy 代理所有 Service 类
		List<Class<?>> serviceClassList = ClassUtil.getClassListByAnnotation(Service.class);
		proxyMap.put(TransactionProxy.class, serviceClassList);
	}

	private static List<Class<?>> createTargetClassList(Aspect aspect) throws Exception {
		List<Class<?>> targetClassList = new ArrayList<Class<?>>();
		Class<? extends Annotation> annotation = aspect.value();

		// 若注解不为空且不是 Aspect 注解，则添加应用包名下带有该注解的所有类
		if (annotation != null && !annotation.equals(Aspect.class)) {
			targetClassList.addAll(ClassUtil.getClassListByAnnotation(annotation));
		}

		return targetClassList;
	}

	private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, List<Class<?>>> proxyMap) throws Exception {
		Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>, List<Proxy>>();
		// 遍历 Proxy Map
		for (Map.Entry<Class<?>, List<Class<?>>> proxyEntry : proxyMap.entrySet()) {
			// 分别获取 map 中的 key 与 value
			Class<?> proxyClass = proxyEntry.getKey();
			List<Class<?>> targetClassList = proxyEntry.getValue();
			// 遍历目标类列表
			for (Class<?> targetClass : targetClassList) {
				// 创建代理类（切面类）实例
				Proxy baseAspect = (Proxy) proxyClass.newInstance();
				// 初始化 Target Map
				if (targetMap.containsKey(targetClass)) {
					targetMap.get(targetClass).add(baseAspect);
				} else {
					List<Proxy> baseAspectList = new ArrayList<Proxy>();
					baseAspectList.add(baseAspect);
					targetMap.put(targetClass, baseAspectList);
				}
			}
		}
		return targetMap;
	}
}